package callchain;

import java.util.ArrayList;
import java.util.List;

import callchain.lightcallgraph.LightCallGraph;

public class CallChainFinder {
	private List<List<Integer>> allCallChains = new ArrayList<List<Integer>>();
	private LightCallGraph cg;
	
	public CallChainFinder(LightCallGraph cg){
		this.cg = cg;
	}
	
	public void clearCallChains(){
		allCallChains.clear();
	}

	public List<List<Integer>> getAllCallChains(){
		return allCallChains;
	}
	
	public void findAllCallChains(Integer startNodeIndex, Integer endNodeIndex, List<Integer> tempPath){
		   if( startNodeIndex == null || endNodeIndex == null ){
			   System.err.println("Error: node index should never be null.");
			   return;
		   }
		   
		   // check if we've reached our destination
		   if (startNodeIndex.equals(endNodeIndex)) {
		      // bookkeeping: add the last node and make a copy of path for later
		      // path.add(fromNode);
		      // allPaths.add(new ArrayList(path));
		      List<Integer> pathCopy = new ArrayList<Integer>(tempPath);
		      pathCopy.add(startNodeIndex);
		      allCallChains.add(pathCopy);
		      return;
		   }

		   // check if we've been here before (no cycles in path)
		   if (tempPath.contains(startNodeIndex))
		      return;

		   // bookkeeping: mark the fromNode as visited
		   tempPath.add(startNodeIndex);
		   //
		   // walk over all edges departing from the fromNode
		   List<Integer> currentTargets = cg.getTargets(startNodeIndex);
		   if( currentTargets != null ){
			   for(Integer tgtNodeIndex : currentTargets){
				   findAllCallChains(tgtNodeIndex, endNodeIndex, tempPath);
			   }
		   }
		   
		   // unmark this node again
		   tempPath.remove(tempPath.size()-1);
	}
}
